package com.kk.threadpool.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author MH
 */
@Configuration
@EnableAsync
public class PoolConfig {

    /**
     * ThreadPoolExecutor是Java的线程池
     * 这个需要手动关闭线程池
     */
    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        //获取cpu核心数
        int i = Runtime.getRuntime().availableProcessors();
        //核心线程数
        int corePoolSize = i * 2;
        // 最大线程数
        int maximumPoolSize  = corePoolSize;
        // 除了核心线程，其他线程的空闲存活时间
        long keepAliveTime = 60L;
        // 任务队列
        // LinkedBlockingQueue（无界队列）
        // ArrayBlockingQueue（FIFO 有界队列） PriorityBlockingQueue（优先级队列）
        // SynchronousQueue（同步移交队列），只有在使用无界线程池或者有饱和策略时才建议使用该队列。
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue(1);

        // 线程工厂，如果没有另外说明，则在同一个ThreadGroup 中一律使用Executors.defaultThreadFactory() 创建线程，并且这些线程具有相同的NORM_PRIORITY 优先级和非守护进程状态。
        ThreadFactory threadFactory = Executors.defaultThreadFactory();

        // 拒绝策略，当线程数已经达到maxPoolSize，且队列已满，会拒绝新任务。
        // 当线程池被调用shutdown()后，会等待线程池里的任务执行完毕再shutdown。如果在调用shutdown()后再提交任务，会拒绝新任务。
        // AbortPolicy 丢弃任务，抛运行时异常。
        // CallerRunsPolicy 由当前调用的任务线程执行任务。
        // DiscardPolicy 忽视，什么都不会发生。
        // DiscardOldestPolicy 从队列中踢出最先进入队列（最后一个执行）的任务。
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, handler);
        return executor;
    }

    /**
     *  ThreadPoolTaskExecutor是spring封装的线程池
     * 这个会自动关闭线程池
     * 这个可以配合   @EnableAsync @Async 使用。
     */
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(1);
        // 最大线程数
        executor.setMaxPoolSize(1);
        // 任务队列大小
        executor.setQueueCapacity(1);
        // 线程名前缀
        executor.setThreadNamePrefix("Hello-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // 所有任务结束后在再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 执行初始化
        executor.initialize();
        return executor;
    }
}
